/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2011.08.22                                          *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_smlt_SimulationEnsemble_h
#define FreeMAPs_include_COMMON_smlt_SimulationEnsemble_h

#include "FreeMAPsConfig.h"

//COMMON headers
#include "COMMON/base/StateIndicator.h"
#include "COMMON/tbox/StartupShutdownManager.h"


namespace FreeMAPs
{

//forward declarations
class PDEEquationEnsembleStrategy;
class NonPDEEquationEnsembleStrategy;

/**
 * SimulationEnsemble is the top class in doing simulation.
 * A simulation_ensemble may consists several equation_ensembles,
 * each equation ensemble have a single system to be solved.
 * for examples, a simulation_ensemble may contains two region of A and B,
 * A is a fluid region and NS equations will be solved and B may be
 * a solid region which have two equation ensambles of thermal conductor and stress equation.
 */
class SimulationEnsemble : public StateIndicator
{
public:

    virtual
    ~SimulationEnsemble();

public:

//    inline bool
//    has_pde_equation_ensemble() const;

//    inline bool
//    has_pde_equation_ensemble(
//        const std::string& eq_name) const;

//    inline bool
//    has_nonpde_equation_ensemble(
//        const std::string& eq_name) const;

//    inline const PDEEquationEnsembleStrategy*
//    get_pde_equation_ensemble(
//        const std::string& eq_name) const;

//    inline PDEEquationEnsembleStrategy*
//    get_pde_equation_ensemble(
//        const std::string& eq_name);

    inline const std::map<std::string, PDEEquationEnsembleStrategy*>&
    get_pde_equation_ensembles() const;

//    inline const std::map<std::string, NonPDEEquationEnsembleStrategy*>&
//    get_nonpde_equation_ensembles() const;


public:

    /**
      * Return a pointer to the single instance of the simulation ensemble.
      * All access to the object is through get_simulation_ensemble().
      *
      * Note that when the manager is accessed for the first time, the
      * Singleton instance is registered with the StartupShutdownManager
      * class which destroys such objects at program completion.  Thus,
      * users of this class do not explicitly allocate or deallocate the
      * Singleton instance.
      */
    static SimulationEnsemble*
    get_instance();

    void
    clear();

    void
    get_from_input (
            const InputDatabase* db);

    friend std::ostream&
    operator << (
            std::ostream& os,
            const SimulationEnsemble& rhs);

    bool
    check_all_info_db(
            const InputDatabase* db);

    /*
     * Deallocate the restart manager instance.  It is not necessary to call
     * this routine at program termination, since it is automatically called
     * by the StartupShutdownManager class.
     */
    static void shutdown_callback();

    //add pde_equation_ensemble to d_pde_equation_ensembles from GUI
    void add_pde_equation_ensembles(
            std::string equation_ensemble_name,
            PDEEquationEnsembleStrategy* pde_equation_ensemble);


private:
    SimulationEnsemble (
            const std::string& object_name);

private:

    typedef StateIndicator Parent;
    /*
     * simulation_ensemble give the region's information such as
     * what is the question to be solved in the region.
     * map<equation_ensemble's name, equation_ensemble>
     */
    std::map<std::string, PDEEquationEnsembleStrategy*> d_pde_equation_ensembles;
#if 0
    std::map<std::string, NonPDEEquationEnsembleStrategy*> d_nonpde_equation_ensembles;
#endif


private:

    static SimulationEnsemble* s_instance;
    /*
     * used for deallocate memory at program completion.
     */
    static StartupShutdownManager::Handler s_shutdown_handler;

private:

    DISALLOW_COPY_AND_ASSIGN (SimulationEnsemble);
};

}

#include "COMMON/smlt/SimulationEnsemble.inl"

#endif
